#pragma once
#include <iostream>
#include "myh/MyLog.hpp"
#include "myh/PthreadMutex.hpp"
#include <vector>
#include <semaphore.h>

template <class T>
class RQueue
{
    static const size_t defaultcap = 10;
    void P(sem_t *_sem)
    {
        int ret = sem_wait(_sem);
        HandleRet("sem_wait", ret);
    }
    void V(sem_t *_sem)
    {
        int ret = sem_post(_sem);
        HandleRet("sem_post", ret);
    }

    void HandleRet(const std::string &funname, int _error)
    {
        if (_error)
        {
            lg.defaultprint("funname", _error);
        }
    }

public:
    RQueue(size_t cap = defaultcap)
        : _cap(cap), _c_i(0), _p_i(0), _cdate(new sem_t), _pspace(new sem_t), _vqueue(cap)

    {
        int ret1 = sem_init(_cdate, 0, 0);
        HandleRet("sem_init", ret1);
        int ret2 = sem_init(_pspace, 0, _cap);
        HandleRet("sem_init", ret2);
    }

    void push(const T &val)
    {
        P(_pspace);

        Guardlock();
        _vqueue[_p_i] = val;
        V(_cdate);
        _p_i = (_p_i + 1) % _cap;
    }

    T pop()
    {
        P(_cdate);

        Guardlock();
        T val = _vqueue[_c_i];
        V(_pspace);
        _c_i = (_c_i + 1) % _cap;

        return val;
    }
    ~RQueue()
    {
        delete _cdate;
        delete _pspace;
    }

private:
    size_t _cap;
    size_t _c_i;
    size_t _p_i;
    sem_t *_cdate;
    sem_t *_pspace;

    __uint64_t _maxcap;
    std::vector<T> _vqueue;
};